package com.yibo.redis.util;

import com.yibo.support.context.SpringContext;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * redis队列  线程不安全
 *
 * @author zhanglei
 */
@SuppressWarnings("unchecked")
public class RedisBlockingQueue implements BlockingQueue<String> {

    /**
     * redisTemplate
     */
    private RedisTemplate redisTemplate;

    /**
     * 队列名称
     */
    private String queueName;

    /**
     * 最大长度
     */
    private int maxSize = Integer.MAX_VALUE;


    public RedisBlockingQueue(String queueName){
        this.queueName = queueName ;
        synchronized (RedisBlockingQueue.class){
            if(redisTemplate == null){
                redisTemplate = SpringContext.getBean(RedisTemplate.class);
            }
        }
    }

    public RedisBlockingQueue(String queueName,int maxSize){
        this(queueName);
        this.maxSize = maxSize;
    }

    /**
     * 添加到队列尾部，如果超过最大范围，则抛出不支持操作异常
     */
    @Override
    public boolean add(String s){
        if(size() >= maxSize){
            throw new UnsupportedOperationException();
        }
        return redisTemplate.opsForList().rightPush(this.queueName,s) > 0;
    }

    /**
     * 添加到队列尾部，如果超过最大范围则返回false
     */
    @Override
    public boolean offer(String s) {
        if(size() >= maxSize){
            return false;
        }
        return redisTemplate.opsForList().rightPush(this.queueName,s) > 0;
    }

    @Override
    public String remove() {
        return this.redisTemplate.delete(this.queueName) ? this.queueName : null;
    }

    /**
     * poll是队列数据结构实现类的方法，从队首获取元素，同时获取的这个元素将从原队列删除；
     * 如果队列为空，抛出异常
     */
    @Override
    public String poll() {
        Object  head =  this.redisTemplate.opsForList().leftPop(queueName);
        if(head == null){
            throw new UnsupportedOperationException();
        }
        return (String) head;
    }

    @Override
    public String element() {
        throw new UnsupportedOperationException();
    }

    /**
     * 获取队列头部元素，如果队列为空，则返回null  删除元素
     */
    @Override
    public String peek() {
        Object head = this.redisTemplate.opsForList().leftPop(queueName);
        return head == null ? null : String.valueOf(head);
    }

    /**
     * put 和 offer一样 不过没有返回值 不会抛异常
     */
    @Override
    public void put(String s) throws InterruptedException {
        offer(s);
    }

    @Override
    public boolean offer(String s, long timeout, TimeUnit unit) throws InterruptedException {
        return  offer(s);
    }

    @Override
    public String take() throws InterruptedException {
        throw new UnsupportedOperationException();
    }

    @Override
    public String poll(long timeout, TimeUnit unit) throws InterruptedException {
        return (String)redisTemplate.opsForList().leftPop(queueName,timeout,unit);
    }

    @Override
    public int remainingCapacity() {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean remove(Object o) {
        return redisTemplate.opsForList().remove(queueName,0,o) == 1;
    }

    @Override
    public boolean containsAll(Collection<?> c) {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean addAll(Collection<? extends String> c) {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean removeAll(Collection<?> c) {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean retainAll(Collection<?> c) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void clear() {
        this.redisTemplate.delete(queueName);
    }

    @Override
    public int size() {
        return (int)(long)redisTemplate.opsForList().size(this.queueName);
    }

    @Override
    public boolean isEmpty() {
        return this.redisTemplate.opsForList().size(queueName) == 0;
    }

    @Override
    public boolean contains(Object o) {
        List<Object> re =  redisTemplate.opsForList().range(queueName,0,
                redisTemplate.opsForList().size(queueName));
        return re.contains(o);
    }

    @Override
    public Iterator<String> iterator() {
        throw new UnsupportedOperationException();
    }

    @Override
    public Object[] toArray() {
        throw new UnsupportedOperationException();
    }

    @Override
    public <T> T[] toArray(T[] a) {
        throw new UnsupportedOperationException();
    }

    @Override
    public int drainTo(Collection<? super String> c) {
        throw new UnsupportedOperationException();
    }

    @Override
    public int drainTo(Collection<? super String> c, int maxElements) {
        throw new UnsupportedOperationException();
    }
}
